package com.macro.mall.es.service.impl;

import com.macro.mall.common.api.CommonResult;
import com.macro.mall.common.dto.EsIndexDto;
import com.macro.mall.es.dto.DocSearchRequest;
import com.macro.mall.es.dto.DocSearchResponse;
import com.macro.mall.es.service.EsService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.*;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.alibaba.nacos.client.utils.EnvUtil.LOGGER;


@Service
@Slf4j
public class EsServiceImpl implements EsService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 创建产品索引
     * @param esIndexDto
     * @return
     */
    @Override
    public CommonResult creatProductIndex(EsIndexDto esIndexDto) {
        CommonResult commonResult = searchIndexChecker(esIndexDto.getIndexName());
        Boolean data = (Boolean) commonResult.getData();
        if (data!=null){
            throw new RuntimeException("索引存在");
        }
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(esIndexDto.getIndexName());
        if (esIndexDto.getIndexMappings() != null) {
            createIndexRequest.mapping(esIndexDto.getIndexMappings(), XContentType.JSON);
        }
        if (esIndexDto.getIndexSetting() != null) {
            createIndexRequest.settings(esIndexDto.getIndexSetting(),XContentType.JSON);
        }
        try {
            restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("创建索引的方法出现异常: 参数: {}, 信息: {}", esIndexDto, e.getMessage());
            throw new RuntimeException(e);
        }
        return CommonResult.success("添加索引成功");
    }
    /**
     * 根据索引名称搜索产品索引
     */
    @Override
    public CommonResult<Map<String, Object>> searchProductIndex(String indexName) {
        CommonResult commonResult = searchIndexChecker(indexName);
        Boolean data = (Boolean) commonResult.getData();
        if (!data){
            throw new RuntimeException("索引不存在");
        }
        GetMappingsRequest getMappingsRequest = new GetMappingsRequest();
        getMappingsRequest.indices(indexName);
        try {
            GetMappingsResponse mapping = restHighLevelClient.indices().getMapping(getMappingsRequest, RequestOptions.DEFAULT);
            Map<String, Object> sourceAsMap = mapping.mappings().get(indexName).getSourceAsMap();
            return CommonResult.success(sourceAsMap);
        } catch (IOException e) {
            log.error("查询索引出现错误: 参数: {}, 错误信息: {}",indexName,e.getMessage());
            throw new RuntimeException(e);
        }
    }
    /**
     * 检查索引是否存在
     */
    @Override
    public CommonResult searchIndexChecker(String indexName) {
        GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
        try {
            restHighLevelClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
            return CommonResult.success(true);
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.NOT_FOUND) {
                return CommonResult.failed("索引不存在");
            }
            throw new RuntimeException("检查索引是否存在时发生 Elasticsearch 异常", e);
        } catch (IOException e) {
            throw new RuntimeException("检查索引是否存在时发生 IO 异常", e);
        }
    }
    /**
     * 更新产品索引
     */
    @Override
    public CommonResult updateIndexProduct(EsIndexDto esIndexDto) {
        if (esIndexDto.getIndexSetting() != null) {
             try {
                UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(esIndexDto.getIndexName());
                updateSettingsRequest.settings(esIndexDto.getIndexSetting(),XContentType.JSON);
                restHighLevelClient.indices().putSettings(updateSettingsRequest,RequestOptions.DEFAULT);
            } catch (IOException e) {
                 log.error("更新索引设置时发生异常：索引名：{}，设置：{}，异常信息：{}",esIndexDto.getIndexName(), esIndexDto.getIndexSetting(),e.getMessage());
                 return CommonResult.failed("更新索引设置时发生异常");
            }
        }
        if (esIndexDto.getIndexMappings()!=null){
            try {
                PutMappingRequest putMappingRequest = new PutMappingRequest(esIndexDto.getIndexName());
                putMappingRequest.source(esIndexDto.getIndexMappings(),XContentType.JSON);
                restHighLevelClient.indices().putMapping(putMappingRequest,RequestOptions.DEFAULT);
            } catch (IOException e) {
                log.error("更新索引映射时发生异常：索引名：{}，映射：{}，异常信息：{}",esIndexDto.getIndexName(),esIndexDto.getIndexMappings(),e.getMessage());
                return CommonResult.failed("更新索引映射时发生异常");
            }
        }
        return CommonResult.failed("索引更新成功");
    }
    /**
     * 删除指定的产品索引
     */
    @Override
    public CommonResult delProductIndex(String indexName) {
        CommonResult commonResult = searchIndexChecker(indexName);
        Boolean data = (Boolean) commonResult.getData();
        if (!data) {
            throw new RuntimeException("索引不存在");
        }
        try {
            DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
            AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
            boolean acknowledged = delete.isAcknowledged();
            if (acknowledged){
                return CommonResult.success("删除成功");
            }else {
                return CommonResult.success("删除失败");
            }
        } catch (IOException e) {
            log.error("更新索引映射时发生异常：索引名：{},异常信息：{}",indexName, e.getMessage());
            throw new RuntimeException(e);
        }
    }
    /**
     * 搜索
     */
    @Override
    public List<DocSearchResponse> search(DocSearchRequest searchRequest) {
        List<DocSearchResponse> results = new ArrayList<>();
        try {
            // 创建搜索请求
            SearchRequest elasticsearchRequest = new SearchRequest(searchRequest.getIndexName());

            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            // 分页
            searchSourceBuilder.from((searchRequest.getPageInfo().getNum() - 1) * searchRequest.getPageInfo().getSize());
            searchSourceBuilder.size(searchRequest.getPageInfo().getSize());

            // 排序
            searchSourceBuilder.sort(searchRequest.getOrderInfo().getOrderField(),
                    SortOrder.valueOf(searchRequest.getOrderInfo().getOrderType().toUpperCase()));

            // 构建实际查询（这里应该根据 searchRequest 的内容来构建）
            // searchSourceBuilder.query(...);

            // 暂时使用 matchAllQuery 作为示例
            searchSourceBuilder.query(QueryBuilders.matchAllQuery());

            // 设置搜索源
            elasticsearchRequest.source(searchSourceBuilder);

            // 执行查询
            SearchResponse response = restHighLevelClient.search(elasticsearchRequest, RequestOptions.DEFAULT);

            // 解析查询结果
            for (SearchHit hit : response.getHits().getHits()) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                DocSearchResponse responseObject = new DocSearchResponse();
                responseObject.setId(hit.getId());
                responseObject.setName(sourceAsMap.get("name") != null ? sourceAsMap.get("name").toString() : "Unknown");

                // 假设价格可能为 null，并处理它
                Double price = sourceAsMap.get("price") != null ? Double.parseDouble(sourceAsMap.get("price").toString()) : 0.0;
                responseObject.setPrice(price);

                // 添加其他字段
                results.add(responseObject);
            }
        } catch (Exception e) {
            // 使用日志框架记录异常
            LOGGER.error("Error during search: ", e);
            // 根据需要抛出或处理异常
            // throw new RuntimeException("Search failed", e);
        }
        return results;
    }

}
